home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
sunrast.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
9KB
|
413 lines
/*
* $Id: sunrast.c,v 0.91 1994/02/20 00:52:54 zhao Pre-Release $
*
*. This file is part of BIT shareware package. After the two weeks of
* free evaluation period, you are encouraged (required) to register
* your copy for a small registration fee, which is $35 for personal use
* and $50 for commercial, government and institutional use.
*
* Copyright(c) 1993, 1994 by T.C. Zhao.
* All rights reserved.
*
* Permission to use, copy, and distribute this software in its entirety
* for non-commercial purposes is hereby granted, provided that the
* above shareware and copyright notices and this permission notice
* appear in all copies and their documentation.
*
* This software may be modified for your own use, but modified versions
* may not be distributed without prior consent of the author.
*
* This software is provided "as is" without expressed or implied
* warranty of any kind.
*
*.
*
* Sun Raster format support.
* For 8 bit images without a colormap, two choices are availble:
* one is to fake a colormap and use the data as the color index
* and the other is simply use the data as the gray intensity
* and respresent the image as T_GRAY(RGB).
*/
#ifndef NO_SUNRAS
#if !defined(lint) && defined(F_ID)
char *id_sr = "$Id: sunrast.c,v 0.91 1994/02/20 00:52:54 zhao Pre-Release $";
#endif
#include "bit.h"
#include "dmalloc.h"
/******************* Limits and defines ***************************/
/* supported format */
#define RT_STANDARD 1
#define RT_BYTE_ENCODED 2
#define RT_FORMAT_RGB 3
/* supported maps */
#define RMT_NONE 0
#define RMT_EQUAL_RGB 1
/********************* local variables ********************/
static int ras_type, ras_depth, ras_length, ras_maplength;
/******************************************************************/
int
RAS_desc(IPTR im)
{
FILE *fp = im->fp;
int i, ras_maptype;
CMPTR cm = im->cmap;
/* skip 4 bytes signature */
(void) get4MSBF(fp);
/* basic properties of the image */
im->w = get4MSBF(fp);
im->h = get4MSBF(fp);
ras_depth = get4MSBF(fp);
ras_length = get4MSBF(fp);
ras_type = get4MSBF(fp);
ras_maptype = get4MSBF(fp);
ras_maplength = get4MSBF(fp);
#ifdef MDEBUG
M_debug("RAS_desc", "w=%d h=%d depth=%d", im->w, im->h, ras_depth);
M_debug("RAS_desc", "type=%d length=%d", ras_type, ras_length);
M_debug("RAS_desc", "maptype=%d maplen=%d", ras_maptype, ras_maplength);
#endif
/* check */
if (ras_type != RT_STANDARD &&
ras_type != RT_BYTE_ENCODED &&
ras_type != RT_FORMAT_RGB)
{
Bark("RAS_desc", "Unknown/unsupported raster type: %d", ras_type);
return -1;
}
/* check colormaps */
cm->colors = 0;
if (ras_maptype != RMT_EQUAL_RGB)
{
for (i = 0; i < ras_maplength; i++)
(void) getc(fp);
}
else
{
im->colors = cm->colors = ras_maplength / 3;
if (Badfread(cm->ct[0], 1, cm->colors, fp) ||
Badfread(cm->ct[1], 1, cm->colors, fp) ||
Badfread(cm->ct[2], 1, cm->colors, fp))
{
Bark("RAS_Desc", "Error reading colormap");
return -1;
}
}
/* check image type */
switch (ras_depth)
{
case 1: /* 2 colors */
im->colors = cm->colors = 2;
if (ras_maplength == 0 && ras_maptype == RMT_NONE)
{
im->type = T_BW;
cm->ct[0][0] = cm->ct[1][0] = cm->ct[2][0] = PCMAXV;
cm->ct[0][1] = cm->ct[1][1] = cm->ct[2][1] = 0;
}
else
{
im->type = T_CMAP;
}
break;
case 8: /* map, also could be grayscale */
if (ras_maplength == 0 && ras_maptype == RMT_NONE)
{
#ifdef RAS_FAKE_MAP
im->type = T_GMAP;
im->colors = cm->colors = PCMAX;
for (i = 0; i <= PCMAXV; i++)
cm->ct[0][i] = cm->ct[1][i] = cm->ct[2][i] = i;
#else
im->type = T_GRAY;
#endif
}
else
{
im->type = T_CMAP;
}
break;
case 24:
case 32:
im->type = T_RGBA;
break;
default:
Bark("RAS_desc", "Bad depth: %d", ras_depth);
return -1;
}
return 0;
}
static long ras_rlines;
static int
ras_decode(IPTR im, register unsigned char *pp)
{
register int i, c, cnt;
register unsigned char *enc, *eh;
int err = (!(enc = eh = malloc(ras_length)) ||
Badfread(enc, 1, ras_length, im->fp));
/* decode on the fly */
for (i = 0; i < ras_length;)
{
if ((c = *enc++) != 128)
{
*pp++ = c;
i++;
}
else
{ /* escape */
if ((cnt = 1 + *enc++) == 1)
{
*pp++ = 128;
i += 2;
}
else
{
for (c = *enc++; --cnt >= 0;)
*pp++ = c;
i += 3;
}
}
}
free(eh);
return err;
}
int
RAS_load(IPTR im)
{
register unsigned char *pp, *ph;
register int i, h;
int linelen = (im->w * ras_depth + 15) / 16 * 2, err = 0;
void *mm;
ras_rlines = progress_report("Loading Ras ...", im->h);
pp = ph = malloc(im->h * linelen);
/* read in the raster */
switch (ras_type)
{
case RT_BYTE_ENCODED:
err = ras_decode(im, pp);
break;
default:
err = (Badfread(ph, 1, im->h * linelen, im->fp));
break;
}
if (err)
{
Bark("RAS_load", "Error reading image");
return -1;
}
/****** unpack to bit format *********/
mm = im->mraster;
h = im->h;
for (pp = ph, i = 0; i < h; i++, pp = ph + i * linelen)
{
REPORT(i, ras_rlines);
switch (ras_depth)
{
case 24:
case 32:
{
register rgba_t *qs, *q = ((rgba_t **) mm)[h - 1 - i];
register int r, g, b;
if (ras_type == RT_FORMAT_RGB)
{
for (qs = q + im->w; q < qs; q++)
{
if (ras_depth == 32)
pp++;
r = *pp++;
g = *pp++;
b = *pp++;
*q = Pack(r, g, b);
}
}
else
{
for (qs = q + im->w; q < qs; q++)
{
if (ras_depth == 32)
pp++;
b = *pp++;
g = *pp++;
r = *pp++;
*q = Pack(r, g, b);
}
}
}
break;
case 8:
#ifndef RAS_FAKE_MAP
if (ras_maplength == 0)
{
rgba_t *qs, *q = ((rgba_t **) mm)[h - 1 - i];
for (qs = q + im->w; q < qs; q++, pp++)
*q = Pack(*pp, *pp, *pp);
}
else
#endif
{
register ci_t *qs, *q = ((ci_t **) mm)[h - 1 - i];
for (qs = q + im->w; q < qs; q++, pp++)
*q = *pp;
}
break;
case 1:
{
register ci_t *qs, *q = ((ci_t **) mm)[h - 1 - i];
register int mask;
for (mask = 0x80, qs = q + im->w; q < qs; q++)
{
if (!mask)
{
pp++;
mask = 0x80;
}
*q = (*pp & mask) ? 1 : 0;
mask >>= 1;
}
}
break;
}
}
free(ph);
remove_progress_report();
return 0;
}
#define RAS_MAGIC 0x59a66a95
/* only write standard raster files */
int
RAS_dump(IPTR im)
{
FILE *fp = im->fp;
int linelen = (im->w * ras_depth + 15) / 16 * 2, i, h;
unsigned char *tmpline, *th;
CMPTR cm = im->cmap;
ras_rlines = progress_report("Writing SunRas ...", im->h);
put4MSBF(RAS_MAGIC, fp);
put4MSBF(im->w, fp);
put4MSBF(im->h, fp);
ras_depth = IS_RGBA(im) ? 24 : (IS_BW(im) ? 1 : 8);
put4MSBF(ras_depth, fp);
/* length is useless for standard type */
put4MSBF((im->w * im->h * ras_depth) / 8, fp);
put4MSBF(RT_STANDARD, fp);
if (IS_CI(im))
{
put4MSBF(RMT_EQUAL_RGB, fp);
put4MSBF(cm->colors * 3, fp);
fwrite(cm->ct[0], 1, cm->colors, fp);
fwrite(cm->ct[1], 1, cm->colors, fp);
fwrite(cm->ct[2], 1, cm->colors, fp);
}
else
{
#ifdef RAS_FAKE_MAP
cm->colors = PCMAX;
put4MSBF(RMT_EQUAL_RGB, fp);
put4MSBF(cm->colors * 3, fp);
for (i = 0; i < cm->colors; i++)
cm->ct[0][i] = cm->ct[1][i] = cm->ct[2][i] = i;
fwrite(cm->ct[0], 1, cm->colors, fp);
fwrite(cm->ct[1], 1, cm->colors, fp);
fwrite(cm->ct[2], 1, cm->colors, fp);
#else
put4MSBF(RMT_NONE, fp);
put4MSBF(0, fp);
#endif
}
/* raster data */
linelen = (im->w * ras_depth + 15) / 16 * 2;
tmpline = th = malloc(linelen);
h = im->h;
for (i = 0; i < h; i++, tmpline = th)
{
REPORT(i, ras_rlines);
if (ras_depth == 8)
{
if (IS_CI(im))
{
ci_t *ci = ((ci_t **) im->mraster)[h - 1 - i], *cis;
for (cis = ci + im->w; ci < cis; ci++)
*tmpline++ = *ci;
}
else
{ /* true grayscale */
rgba_t *p = ((rgba_t **) im->mraster)[h - 1 - i],
*ps;
for (ps = p + im->w; p < ps; p++)
*tmpline++ = get_R(*p);
}
}
else if (ras_depth == 24)
{
rgba_t *q = ((rgba_t **) im->mraster)[h - 1 - i], *qs;
register int r, g, b;
for (qs = q + im->w; q < qs; q++)
{
Unpack(*q, r, g, b);
*tmpline++ = b;
*tmpline++ = g;
*tmpline++ = r;
}
}
else if (ras_depth == 1)
{
ci_t *ci = ((ci_t **) im->mraster)[h - 1 - i], *cis;
register int k, bit;
for (k = bit = 0, cis = ci + im->w; ci < cis; ci++)
{
k = (k << 1) | *ci;
if (++bit == 8)
{
*tmpline++ = k;
k = bit = 0;
}
}
if (bit)
{ /* leftover */
k <<= (8 - bit);
*tmpline++ = k;
}
}
fwrite(th, 1, linelen, fp);
}
free(th);
remove_progress_report();
return fflush(fp);
}
#endif /* NO_SUNRAS */